package Servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;

import Components.NamingUtil;
import Components.RequestUtil;
import Components.SessionUtil;
import Loggers.MyLogger;

public class MyCometServlet extends HttpServlet implements CometProcessor {

	protected Map<String, HttpServletResponse> onlineURMapping;

	@Override
	public void destroy() {

	}

	@Override
	public ServletConfig getServletConfig() {
		return null;
	}

	@Override
	public String getServletInfo() {
		return null;
	}

	@Override
	public void init(ServletConfig arg0) throws ServletException {
		super.init(arg0);
		onlineURMapping = new HashMap<String, HttpServletResponse>();
	}

	@Override
	public void service(ServletRequest arg0, ServletResponse arg1)
			throws ServletException, IOException {

	}

	@Override
	public void event(CometEvent event) throws IOException, ServletException {

		HttpServletRequest request = event.getHttpServletRequest();
		HttpServletResponse response = event.getHttpServletResponse();
		if (event.getEventType() == CometEvent.EventType.BEGIN) {

			/***************
			 * resolve the speaker and listener, sending messege to listener and
			 * record this conversation
			 */

			String methodName = RequestUtil.getParamFromReq(request,
					"methodName");

			if ("meetSomebody".equalsIgnoreCase(methodName)) {
				String cu = (String) SessionUtil.getUID(request);
				RequestUtil.getParamFromReq(request, NamingUtil.currentSUID);
				String sb = meetSomebody(cu, response);
				PrintWriter pw = response.getWriter();
				pw.println(sb);
				pw.flush();
				pw.close();
			} else if ("sendMessageTo".equalsIgnoreCase(methodName)) {
				String user_listen = RequestUtil.getParamFromReq(request,
						NamingUtil.currentLUID);
				String message = RequestUtil
						.getParamFromReq(request, "message");
				try {
					sendMessageTo(user_listen, message);
				} catch (Exception e) {
					MyLogger.log(e.getMessage());
				}
			}

			MyLogger.log("BEGIN");
		}

		else if (event.getEventType() == CometEvent.EventType.ERROR) {
			event.close();
			MyLogger.log("ERROR");
		}

		else if (event.getEventType() == CometEvent.EventType.END) {
			event.close();
			MyLogger.log("END");

		} else if (event.getEventType() == CometEvent.EventType.READ) {
			MyLogger.log("READ");
		}

	}

	/**
	 * retrieve one online user
	 * 
	 * @param curUserId
	 * @param response
	 * @return String
	 */
	private String meetSomebody(String curUserId, HttpServletResponse response) {

		/************************************************************************
		 * if exists online users , then return the first one in cache if the
		 * applying user is not recorded, then put him into the cache
		 ************************************************************************/
		Set<String> onlineUsers = this.onlineURMapping.keySet();

		if (!onlineUsers.contains(curUserId)) {
			this.onlineURMapping.put(curUserId, response);
		}
		if (!onlineUsers.isEmpty()) {
			String sb = onlineUsers.iterator().next();
			sb = sb == curUserId ? onlineUsers.iterator().next() : sb;
			return sb;
		} else {
			return null;
		}

	}

	public void sendMessageTo(String user_listen, String message)
			throws Exception {
		if (this.onlineURMapping.containsKey(user_listen)) {
			PrintWriter pw = this.onlineURMapping.get(user_listen).getWriter();
			pw.println(message);
			pw.flush();
			pw.close();
		} else {
			throw new Exception(user_listen + " has left");
		}
	}

}
